package fr.cephb.joperon.core.iterator;

/**
 * Implementation of an iterator returning only
 * the values accepted by its method <code>accept</code>
 * @author lindenb
 *
 * @param <T> delegate type
 * @param <V> an optional user value, use java.lang.Object if not used
 */
public abstract class FilterIterator<T,V> extends AbstractIterator<T> {
	private AbstractIterator<T> delegate;
	private V userValue=null;
	/**
	 * Constructor
	 * @param delegate delegate iterator
	 * @param userValue a user value
	 */
	public FilterIterator(AbstractIterator<T> delegate,V userValue)
		{
		this.delegate=delegate;
		this.userValue=userValue;
		}
	
	/**
	 * Constructor
	 * @param delegate delegate iterator
	 */
	public FilterIterator(AbstractIterator<T> delegate)
		{
		this(delegate,null);
		}
	
	/**
	 * get the user value (see constructor)
	 * might be used by the <b>accept</b> method
	 * @return the user value
	 */
	public V getUserValue() {
		return userValue;
		}
	
	/** 
	 * return wether we should accept the current value returned by
	 * the delegate iterator
	 * @param object the delegate value
	 * @return false if we should ignore this value
	 */
	public abstract boolean accept(T object);
	
	@Override
	public boolean hasNext()
		{
		if(this.eofMet) return false;
		if(this._hasNextTested) return this._hasNext;
		this._hasNextTested=true;
		
		while(true)
			{
			this._nextValue=null;
			this._hasNext=false;
			if(this.eofMet) return false;
			
			if(!delegate.hasNext())
				{
				close();
				return false;
				}
			this._nextValue=delegate.next();
			if(!accept(this._nextValue))
				{
				continue;
				}
			this._hasNext=true;
			return true;
			}
		}

@Override
/** calls delegate.close(); */
public void close()
	{
	delegate.close();
	super.close();
	}	

}
